﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using HandyControl.Controls;
using HandyControl.Data;
using MeasureAbstract.Base;
using MeasureAbstract.IFarfieldMeasure;
using MeasureAbstract.IMotionDevice;
using MeasureAbstract.ISilentAreaMeasure;
using MeasureLibrary.SilentAreaMeasure;

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using 紧缩场反射面装调测试系统.Controll;
using LiveChartsCore.SkiaSharpView;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Windows.Controls;
using LiveChartsCore.SkiaSharpView.WPF;
using LiveChartsCore.SkiaSharpView.VisualElements;
using LiveChartsCore.Kernel;
using LiveChartsCore.SkiaSharpView.Painting;
using SkiaSharp;
using System.Text.Json;
using LiveChartsCore;
using NPOI.SS.Formula.Functions;
using LiveChartsCore.Drawing;
using System.Threading;
using System.Windows.Data;
using System.Globalization;

namespace 紧缩场反射面装调测试系统.ViewModels
{
    public partial class ResultAnalysisViewModel : ObservableObject
    {
        private dynamic? _Measure;
        public dynamic? Measure
        {
            get { return _Measure; }
            set { SetProperty(ref _Measure, value); }
        }


        public ResultAnalysisViewModel()
        {
            LVC.ZoomMode = LiveChartsCore.Measure.ZoomAndPanMode.X;
            LVC.TooltipPosition = LiveChartsCore.Measure.TooltipPosition.Top;
            LVC.Title = new LabelVisual
            {
                Text = "单频点分析结果",
                TextSize = 20,
                Padding = new LiveChartsCore.Drawing.Padding(5),
                Paint = new SolidColorPaint(SKColors.DarkSlateGray)

            };
            LVC.Series = new ISeries[]
            {
                new LineSeries<Data>
                {
                    GeometrySize = 4,
                    Name = "实际曲线",
                    Fill = null,
                    Values=DisplayDatas,
                    YToolTipLabelFormatter = (p) => { return $"( {p.Coordinate.SecondaryValue.ToString("F3")} , {p.Coordinate.PrimaryValue.ToString("F3")} )"; },
                    Mapping = (city, chartPoint) =>
                    {
                        return new Coordinate(city.X, city.Y);
                    }

                },
                new LineSeries<Data>
                {
                    GeometrySize = 4,
                    Name = "拟合曲线",
                    Fill = null,
                    Values=DisplayDatas,
                    YToolTipLabelFormatter = (p) => { return $"( {p.Coordinate.SecondaryValue.ToString("F3")} , {p.Coordinate.PrimaryValue.ToString("F3")} )"; },
                    Mapping = (city, chartPoint) =>
                    {
                        return new Coordinate(city.X, city.Y_Fit);
                    }

                }
            };
            




            LVCSummary.Title = new LabelVisual
            {
                Text = "所有频点分析结果汇总",
                TextSize = 15,
                Paint = new SolidColorPaint(SKColors.DarkSlateGray)

            };
            LVCSummary.Series = new ISeries[]
            {
                new LineSeries<ResultSummaryItem>
                {
                    DataPadding = new LvcPoint(0, 0.5),
                    GeometrySize = 4,
                    Name = "总变差",
                    Fill = null,
                    //YToolTipLabelFormatter = (p) => { return $"( {ValueToUnit(p.Coordinate.SecondaryValue)} , {p.Coordinate.PrimaryValue.ToString("F3")} )"; },
                    YToolTipLabelFormatter = (p) => { return $"{p.Coordinate.PrimaryValue.ToString("F3")}"; },
                    Values = ResultSummary,
                    Mapping = (city, chartPoint) =>
                    {
                        return new Coordinate(city.Frequency, city.TotalVariation);
                    }
        },
                new LineSeries<ResultSummaryItem>
                {
                    DataPadding = new LvcPoint(0, 0.5),
                    GeometrySize = 4,
                    Name = "锥销",
                    Fill = null,
                    //YToolTipLabelFormatter = (p) => { return $"( {ValueToUnit(p.Coordinate.SecondaryValue)} , {p.Coordinate.PrimaryValue.ToString("F3")} )"; },
                    YToolTipLabelFormatter = (p) => { return $"{p.Coordinate.PrimaryValue.ToString("F3")}"; },
                    Values = ResultSummary,
                    Mapping = (city, chartPoint) =>
                    {
                        return new Coordinate(city.Frequency, city.TaperPin);
                    }
                },
                new LineSeries<ResultSummaryItem>
                {
                    DataPadding = new LvcPoint(0, 0.5),
                    GeometrySize = 4,
                    Name = "纹波",
                    Fill = null,
                    //YToolTipLabelFormatter = (p) => { return $"( {ValueToUnit(p.Coordinate.SecondaryValue)} , {p.Coordinate.PrimaryValue.ToString("F3")} )"; },
                    YToolTipLabelFormatter = (p) => { return $"{p.Coordinate.PrimaryValue.ToString("F3")}"; },
                    Values = ResultSummary,
                    Mapping = (city, chartPoint) =>
                    {
                        return new Coordinate(city.Frequency, city.DifferenceValue);
                    }
                }
            };
            //LVCSummary.AnimationsSpeed = TimeSpan.FromMilliseconds(300);
            LVCSummary.XAxes = new LiveChartsCore.SkiaSharpView.Axis[]
            {
                new LiveChartsCore.SkiaSharpView.Axis()
                {
                    TextSize=13,
                    Labeler=(v)=>{ return ValueToUnit(v); },

                }
            };

            LVCSummary.YAxes = new LiveChartsCore.SkiaSharpView.Axis[]
            {
                new LiveChartsCore.SkiaSharpView.Axis()
                {
                    TextSize=13,
                    MinStep=2,
                }
            };
        }


        public void Update(ObservableCollection<Data> New)
        {
            if (New == null) return;
            DisplayDatas.Clear();
            foreach(var temp in New)
            {
                DisplayDatas.Add(temp);
            }

        }


        public string ValueToUnit(double value)
        {
            double F = value;
            string F_str = "";
            if (F / 1000000000 >= 1)
            {
                //GHz
                F_str = (F / 1000000000).ToString() + "GHz";
            }
            else if (F / 1000000 >= 1)
            {
                //MHz
                F_str = (F / 1000000).ToString() + "MHz";
            }
            else if (F / 1000 >= 1)
            {
                //KHz
                F_str = (F / 1000).ToString() + "KHz";
            }
            else
            {
                F_str = F.ToString() + "Hz";
            }
            return F_str;
        }

            public Result QuadraticFit<T>(List<T> Datas,Func<T,double> SelectX, Func<T, double> SelectY)
        {
            //取出X,Y值
            double[] X = ElectromagneticCalculation.RawProcess.GetArray<T>(Datas, SelectX);
            double[] Y = ElectromagneticCalculation.RawProcess.GetArray<T>(Datas, SelectY);

            if(X.Length<2)
            {
                throw new Exception("X,Y数据小于2，无法拟合");
            }

            if(X.Length != Y.Length)
            {
                throw new Exception("X,Y数据长度不一致，无法拟合");
            }

            //做一个平移？这里好像不对
            double[] XT=new double[X.Length];
            double[] YT=new double[Y.Length];

            double _X=X.Average();
            double _Y=Y.Average();

            for(int i=0;i<X.Length;i++)
            {
                XT[i] = X[i] - _X;
                YT[i] = Y[i] - _Y;
            }

            //求解展示数据
            Result Result = new Result();
            double[] Coefficients = ElectromagneticCalculation.CurveFitting.LeastSquares(XT, YT, 2).Reverse().ToArray();
            Result.QX = $"y = {Coefficients[0].ToString($"F9")}x\u00B2 + {Coefficients[1].ToString($"F9")}x + {Coefficients[2].ToString($"F9")}";

            //原始数据
            Result.O_Max = YT.Max().ToString($"F{SystemManage.SystemConfig.DecimalPlaces}");
            Result.O_Max_Position = XT[Array.IndexOf(YT, YT.Max())].ToString();
            Result.O_Min=YT.Min().ToString($"F{SystemManage.SystemConfig.DecimalPlaces}");
            Result.O_Min_Position= XT[Array.IndexOf(YT, YT.Min())].ToString();
            Result.O_TotalVariation = (YT.Max() - YT.Min()).ToString($"F{SystemManage.SystemConfig.DecimalPlaces}");


            //拟合曲线反推数据
            double[] Y_Fit=new double[X.Length];
            for(int i=0;i<YT.Length;i++)
            {
                Y_Fit[i] = Coefficients[0] * XT[i] * XT[i] + Coefficients[1] * XT[i] + Coefficients[2];
            }
            Result.F_Max=Y_Fit.Max().ToString($"F{SystemManage.SystemConfig.DecimalPlaces}");
            Result.F_Max_Position= XT[Array.IndexOf(Y_Fit, Y_Fit.Max())].ToString();
            Result.F_Min = Y_Fit.Min().ToString($"F{SystemManage.SystemConfig.DecimalPlaces}");
            Result.F_Min_Position = XT[Array.IndexOf(Y_Fit, Y_Fit.Min())].ToString();
            Result.F_TaperPin=(Y_Fit.Max()-Y_Fit.Min()).ToString($"F{SystemManage.SystemConfig.DecimalPlaces}");
            //原始数据-拟合数据
            double[] Y_Ripple=new double[X.Length];
            for(int i=0;i<X.Length;i++)
            {
                Y_Ripple[i] = YT[i] - Y_Fit[i];
            }
            Result.R_Max=Y_Ripple.Max().ToString($"F{SystemManage.SystemConfig.DecimalPlaces}");
            Result.R_Max_Position = XT[Array.IndexOf(Y_Ripple, Y_Ripple.Max())].ToString();
            Result.R_Min = Y_Ripple.Min().ToString($"F{SystemManage.SystemConfig.DecimalPlaces}");
            Result.R_Min_Position = XT[Array.IndexOf(Y_Ripple, Y_Ripple.Min())].ToString();
            //Result.R_DifferenceValue = "±"+((Y_Ripple.Max() - Y_Ripple.Min())/2).ToString($"F{SystemManage.SystemConfig.DecimalPlaces}");
            Result.R_DifferenceValue = "±"+(Math.Abs(Y_Ripple.Max())>=Math.Abs(Y_Ripple.Min())?Math.Abs(Y_Ripple.Max()) : Math.Abs(Y_Ripple.Min())).ToString($"F{SystemManage.SystemConfig.DecimalPlaces}");

            Result.ResultData = new ObservableCollection<Data>();
            for (int i=0;i<XT.Length;i++)
            {
                //Result.X[i] = XT[i];
                //Result.Y[i] = YT[i];
                //Result.Y_Fit[i] = Y_Fit[i];
                Data data = new Data();
                data.X= XT[i];
                data.Y= YT[i];
                data.Y_Fit = Y_Fit[i];
                Result.ResultData.Add(data);
            }


            return Result;
        }

       

        #region 与图表相关的操作
        public CartesianChart LVC { get; set; } = new CartesianChart();
        public CartesianChart LVCSummary { get; set; } = new CartesianChart();

        [RelayCommand]
        public void AddLine(string Name)
        {
            //设置曲线的属性（名称一般设置为频率值）
            //设置曲线的数据
            //将曲线添加到图表数据
            bool Y = false;
            foreach (var temp in LVC.Series)
            {
                if (temp.Name == Name)
                {
                    //曲线已存在
                    Y = true;
                }
            }

            if (!Y)
            {
                var aaa = LVC.Series.ToList();
                var temp = new LineSeries<DataItem>
                {
                    GeometrySize = 4,
                    Name = Name,
                    Fill = null,
                    YToolTipLabelFormatter = (p) => { return $"( {p.Coordinate.SecondaryValue.ToString("F3")} , {p.Coordinate.PrimaryValue.ToString("F3")} )"; },
                    Values = DataDictFrequency_PositionCollection[double.Parse(Name)],

                };
                //添加曲线
                aaa.Add(temp);
                LVC.Series = aaa.ToArray();
                SwitchDataType(DataType);

            }

        }

        public void SwitchLine(string Name)
        {
            foreach(var temp in DataDictFrequency_ResultCollection)
            {
                if(temp.Key==double.Parse(Name))
                {
                    foreach(var temp2 in temp.Value)
                    {
                        if(temp2.DataType==DataType)
                        {
                            DisplayResult = temp2;
                            Update(DisplayResult.ResultData);
                            return;
                        }
                    }

                }
            }
        }

        [RelayCommand]
        public void RemoveLine(string Name)
        {
            //根据名称找到曲线（名称一般设置为频率值）
            //移除曲线
            bool Y = false;
            var A = LVC.Series.ToList();
            foreach (var temp in A)
            {
                if (temp.Name == Name)
                {
                    //曲线已存在
                    Y = true;
                    A.Remove(temp);
                    LVC.Series = A.ToArray();
                    break;
                }
            }


        }

        [RelayCommand]
        public void SwitchDataType(string Type)
        {
            if (string.IsNullOrEmpty(SelectFrequency)) return;
            if (DataDictFrequency_ResultCollection == null) return;
            foreach (var temp in DataDictFrequency_ResultCollection)
            {
                if (temp.Key == double.Parse(SelectFrequency))
                {
                    foreach (var temp2 in temp.Value)
                    {
                        if (temp2.DataType == Type)
                        {
                            DisplayResult = temp2;
                            Update(DisplayResult.ResultData);
                            return;
                        }
                    }

                }
            }

        }
        [RelayCommand]
        public void SwitchDataTypeSummary(string Type)
        {
            //变更图表显示的变量
            //更改图表标题
            //查找当前有几条曲线，记录下来
            //将新曲线的数据添加到图表
            SummaryResult(Type);

        }
        #endregion



        #region 与外部数据文件相关的操作

        public string FilePath
        {
            get { return _FilePath; }
            set
            {
                SetProperty(ref _FilePath, value);
                //更新图表
                if (!string.IsNullOrEmpty(value))
                {
                    ReadDatas();
                }
            }
        }
        private string _FilePath = "";


        List<string> AlreadyExistFiles = new List<string>();

        public async void ReadDatas()
        {
            await Task.Run(() =>
            {
                string[] Files = FilePath.Split("\n");
                foreach (string File in Files)
                {
                    if (File != "")
                    {
                        //验证数据文件是否有效，给出提示
                        if (!System.IO.File.Exists(File))
                        {
                            Growl.Warning($"{File}不存在!");
                            continue;
                        }

                        if (AlreadyExistFiles.Contains(File))
                        {
                            Growl.Warning($"{File}已经存在!");
                            continue;
                        }
                        ResetData();
                        DataManage.ReadFromFile(File, out MeasureData);
                        if (MeasureData.DocumentIdentificationMark != "CP_DATA")
                        {
                            Growl.Warning($"{File}不是有效的数据文件!\n文件识别标记{MeasureData.DocumentIdentificationMark}不匹配！");
                            continue;
                        }

                        AlreadyExistFiles.Add(File);
                        //解析数据文件，将包含的数据格式填入下面的选项中
                        DataClassify(MeasureData, ref DataDictFrequency_PositionCollection);
                       
                    }
                }

                //读取文件完毕
                GrowlInfo Info = new GrowlInfo();
                Info.WaitTime = 0;
                Info.Message = "读取文件完毕!";
                Growl.Success(Info);
                //分析数据
                AnalyzeData();
                //选中第一个数据类型、频点
                DataType = DataTypeList[0];
                SelectFrequency = FrequencyList[0];
                Info.Message = "分析数据完毕!";
                Growl.Success(Info);
            });
        }

        #endregion


        #region 与当前测量数据相关

        static T DeepCopy<T>(T obj)
        {
            string json = JsonSerializer.Serialize<T>(obj);

            // 反序列化
            return JsonSerializer.Deserialize<T>(json);
            
        }
        //将测量数据复制过来，不是引用
        public MeasureData CopyData(MeasureData Source)
        {
            return DeepCopy<MeasureData>(Source);
        }

        public async void LoadData(MeasureData Source)
        {
            await Task.Run(() => 
            {
                Clear();
                //从测量中复制数据
                MeasureData = CopyData(Source);
                //数据分类
                DataClassify(MeasureData, ref DataDictFrequency_PositionCollection);
                //分析数据
                AnalyzeData();
            });
            
            //选中第一个数据类型、频点
            if(DataTypeList.Count>0&&FrequencyList.Count>0)
            {
                DataType = DataTypeList[0];
                SelectFrequency = FrequencyList[0];
            }
            

            GrowlInfo Info = new GrowlInfo();
            Info.WaitTime = 0;
            Info.Message = "分析数据完毕!";
            Growl.Success(Info);
        }


        #endregion


        #region 与数据处理相关

        MeasureData MeasureData = new MeasureData();//用来保存从文件中读取到的或是从测量页面发送过来的原始数据
        public Dictionary<double, ObservableCollection<DataItem>> DataDictFrequency_PositionCollection; //原始数据解析之后得到的按频点分类的数据


        public ObservableCollection<string> FrequencyList  //存放频点列表
        {
            get { return _FrequencyList; }
            set
            {
                SetProperty(ref _FrequencyList, value);
            }
        }
        private ObservableCollection<string> _FrequencyList = new ObservableCollection<string>();


        public string SelectFrequency
        {
            get { return _SelectFrequency; }
            set
            {
                SetProperty(ref _SelectFrequency, value);
                if (!string.IsNullOrEmpty(value))
                {
                    //更改显示的曲线
                    SwitchLine(_SelectFrequency);
                }
            }
        }
        private string _SelectFrequency = "";





        //将原始数据按频点分类
        public void DataClassify(MeasureData Source, ref Dictionary<double, ObservableCollection<DataItem>> Dest)
        {
            if (Source.DataItems == null)
            {
                Growl.Warning($"包含0条数据!");
                return;
            }
            if (Source.DataItems.Count == 0)
            {
                Growl.Warning($"包含0条数据!");
                return;
            }
            if (Dest == null)
            {
                Dest = new Dictionary<double, ObservableCollection<DataItem>>();
            }
            else
            {
                Dest.Clear();
            }
            foreach (var Item in Source.DataItems)
            {
                DataManage.AddDataItemToFrequencyBaseDict(Item, ref Dest);
            }
            var temp2 = Dest.Keys;
            Application.Current.Dispatcher.Invoke(() =>
            {
                FrequencyList.Clear();
                foreach (var temp in temp2)
                {
                    FrequencyList.Add(temp.ToString());
                }
                foreach (var temp in Source.DataFormat.Split(";"))
                {
                    if (String.IsNullOrEmpty(temp)) continue;
                    DataTypeList.Add(temp.ToString());
                }
              
            });


        }

        [ObservableProperty]
        public ObservableCollection<string> dataTypeList = new ObservableCollection<string>();

        private string dataType = "";
        public string DataType
        {
            get
            {
                return dataType;
            }
            set
            {
                SetProperty(ref dataType, value);
                SwitchDataType(dataType);
                SwitchDataTypeSummary(dataType);
            }
        }


        [RelayCommand]
        public void Clear()
        {
            FilePath = "";
            DataDictFrequency_PositionCollection = new Dictionary<double, ObservableCollection<DataItem>>();
            FrequencyList = new ObservableCollection<string>();
            MeasureData = new MeasureData();
            AlreadyExistFiles.Clear();
            DataTypeList = new ObservableCollection<string>();
            DataType = "";
            DataDictFrequency_ResultCollection = new Dictionary<double, ObservableCollection<Result>>();
            ResultSummary.Clear();
            DisplayResult = new Result();
            DisplayDatas.Clear();

        }

        public void ResetData()
        {
            DataDictFrequency_PositionCollection = new Dictionary<double, ObservableCollection<DataItem>>();
            FrequencyList = new ObservableCollection<string>();
            MeasureData = new MeasureData();
            AlreadyExistFiles.Clear();
            DataTypeList = new ObservableCollection<string>();
            DataType = "";
            DataDictFrequency_ResultCollection = new Dictionary<double, ObservableCollection<Result>>();
            ResultSummary.Clear();
            DisplayResult = new Result();
            DisplayDatas.Clear();
        }


        [ObservableProperty]
        public Dictionary<double, ObservableCollection<Result>> dataDictFrequency_ResultCollection; //原始数据解析之后得到的按频点分类的数据

        private ObservableCollection<ResultSummaryItem> ResultSummary = new ObservableCollection<ResultSummaryItem>();//分析结果汇总

        [ObservableProperty]
        private Result displayResult = new Result();

        [ObservableProperty]
        private ObservableCollection<Data> displayDatas = new ObservableCollection<Data>();


        //分析数据，将原始数据中的每个频点的方向图数据进行计算，将分析的结果保存起来
        public void AnalyzeData()
        {
            //根据原始数据，对每一个频点进行计算，得到结果
            if(DataDictFrequency_ResultCollection==null)
            {
                DataDictFrequency_ResultCollection = new Dictionary<double, ObservableCollection<Result>>();
            }
            DataDictFrequency_ResultCollection.Clear();


            foreach(var temp in DataDictFrequency_PositionCollection)
            {
                var tempresults=new ObservableCollection<Result>();

                //对每一个数据类型进行计算
                foreach(var type in DataTypeList)
                {
                    var result = new Result();
                    if(type=="对数幅度")
                    {
                        result = QuadraticFit<DataItem>(temp.Value.ToList(), x => x.Position, y => y.LogarithmicAmplitude);
                        result.DataType = "对数幅度";
                    }
                    if (type == "相位")
                    {
                        result = QuadraticFit<DataItem>(temp.Value.ToList(), x => x.Position, y => y.Phase);
                        result.DataType = "相位";
                    }

                    tempresults.Add(result);
                }


                //保存到结果
                DataDictFrequency_ResultCollection.Add(temp.Key, tempresults);
            }

            //将分析结果汇总
            SummaryResult(DataType);
            
        }

        public async void SummaryResult(string Type)
        {
            if (ResultSummary == null)
            {
                ResultSummary = new ObservableCollection<ResultSummaryItem>();
            }
            ResultSummary.Clear();
            if (DataDictFrequency_ResultCollection == null) return;


            await Application.Current.Dispatcher.Invoke(async () =>
            {
                foreach (var keypair in DataDictFrequency_ResultCollection)
                {
                    foreach (var type in keypair.Value)
                    {
                        if (type.DataType == Type)
                        {
                            ResultSummary.Add(new ResultSummaryItem() { Frequency = keypair.Key, TotalVariation = double.Parse(type.O_TotalVariation), TaperPin = double.Parse(type.F_TaperPin) ,DifferenceValue=double.Parse(type.R_DifferenceValue.Replace("±", "")) });
                            //await Task.Delay(100);  //绘图时给个延时，要不然X轴标签容易挤在一起 具体什么原因导致的不清楚
                        }
                    }
                }
            });

            //下面两行用来解决汇总图标X轴标签挤在一起不展开的问题
            await Task.Delay(1000);
            Application.Current.Dispatcher.Invoke(() => { ResultSummary.Add(null); });
            
            //////////////////////////////////////////////////////
        }


        #endregion













    }

    /// <summary>
    /// 电平角度分析结果
    /// </summary>
    public partial class Result:ObservableObject
    {
        //哪个数据类型的结果，例如对数幅度，相位
        [ObservableProperty]
        private string dataType = "";

        [ObservableProperty]
        private string qX = "";

        [ObservableProperty]
        private ObservableCollection<Data> resultData = new ObservableCollection<Data>(); //保存分析后的结果

        



        [ObservableProperty]
        private string o_Max = "";

        [ObservableProperty]
        private string o_Max_Position = "";

        [ObservableProperty]
        private string o_Min = "";

        [ObservableProperty]
        private string o_Min_Position = "";

        [ObservableProperty]
        private string o_TotalVariation="";

        [ObservableProperty]
        private string f_Max = "";

        [ObservableProperty]
        private string f_Max_Position = "";

        [ObservableProperty]
        private string f_Min = "";

        [ObservableProperty]
        private string f_Min_Position = "";

        [ObservableProperty]
        private string f_TaperPin = "";

        [ObservableProperty]
        private string r_Max = "";

        [ObservableProperty]
        private string r_Max_Position = "";

        [ObservableProperty]
        private string r_Min = "";

        [ObservableProperty]
        private string r_Min_Position = "";

        [ObservableProperty]
        private string r_DifferenceValue = "";
    }

    

    public partial class Data:ObservableObject
    {
        [ObservableProperty]
        public double x;
        [ObservableProperty]
        public double y;
        [ObservableProperty]
        public double y_Fit;
    }



    public partial class ResultSummaryItem:ObservableObject
    {
        [ObservableProperty]
        public double frequency;
        [ObservableProperty]
        public double totalVariation;
        [ObservableProperty]
        public double taperPin;
        [ObservableProperty]
        public double differenceValue;
    }

}
